package compound.repository

import pattern.PatternHelper
import compound.repository.entries.Compound

class SearchService {

  //association to the lookup service
  LookupService lookupService

  /**
   * reference to the searchable lucene
   * service
   */
  def searchableService = null


  boolean transactional = true

  /**
   * executes a generic search against the datbase dependend of regular expressions
   */
  def searchGeneric(String value, Map params = [:]) {

    log.info("generic search string: ${value}")

    Map result = params

    log.info(params)
    
    Long total = 0

    def temp = null
    if (value.matches(PatternHelper.STD_INCHI_KEY_PATTERN)) {
      log.debug "is std inchi code -> using limited search"
      temp = lookupService.lookupByInchiKey(value, params)

      total = lookupService.countlookupByInchiKey(value, params)
    }
    else if (value.matches(PatternHelper.STD_INCHI_PATTERN)) {
      log.debug "is std inchi -> using limited search"

      temp = lookupService.lookupByInchi(value, params)
      total = lookupService.countlookupByInchi(value, params)

    }
    else if (value.matches(PatternHelper.CAS_PATTERN)) {
      log.debug "is cas -> using limited search"

      temp = lookupService.lookupByCas(value, params)
      total = lookupService.countlookupByCas(value, params)

    }
    else if (value.matches(PatternHelper.KEGG_PATTERN)) {

      log.debug "is kegg -> using limited search"

      temp = lookupService.lookupByKegg(value, params)
      total = lookupService.countlookupByKegg(value, params)

    }
    else if (value.matches(PatternHelper.LIPID_MAPS_PATTERN)) {

      log.debug "is lipid maps -> using limited search"

      temp = lookupService.lookupByLipidMapId(value, params)
      total = lookupService.countlookupByLipidMapId(value, params)

    }
    else if (value.matches(PatternHelper.HMDB_PATTERN)) {

      log.debug "is hmdb -> using limited search"

      temp = lookupService.lookupByHMDB(value, params)
      total = lookupService.countlookupByHMDB(value, params)

    }
    else if (value.matches(PatternHelper.SID_PATTERN)) {

      log.debug "is sid -> using limited search"

      temp = lookupService.lookupBySID(Integer.parseInt(value.split(":")[1]), params)
      total = lookupService.countlookupBySID(Integer.parseInt(value.split(":")[1]), params)

    }
    else if (value.matches(PatternHelper.CID_PATTERN)) {

      log.debug "is cid -> using limited search"

      temp = lookupService.lookupByCID(Integer.parseInt(value.split(":")[1]), params)
      total = lookupService.countlookupByCID(Integer.parseInt(value.split(":")[1]), params)

    }
    else {

      log.debug "nothing detected -> using name search"

      temp = lookupService.lookupByName(value, params)
      total = lookupService.countlookupByName(value, params)

    }


    result.total = total

    log.info("query generic result total count: ${result.total}")

    if (temp instanceof Collection) {
      result.results = temp
    }
    else {
      result.results = [temp]
    }

    log.info("query generic result: ${result}")

    return result
  }

  /**
   * executes a lucene/compass search
   */
  def textSearch(String query, Map params = [:]) {
    log.info("lucene search string: ${query}")

    try {
      Map result = Compound.search(query, params)

      log.info("query result: ${result}")

      if (result.results.isEmpty()) {
        log.debug("nothing found, fallback and execute generic search...")
        return searchGeneric(query, params)
      }
      else {
        log.debug "query was executed using lucene"
        return result
      }
    }
    catch (Exception e) {
      log.info "lucene error occured (${e.getMessage()}), fall back to generic search"

      return searchGeneric(query, params)

    }
  }
}
